package com.ddone.util.mock;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * @author ddone
 * @date 2024/5/15-10:01
 */
public class RandomBox<T> {
    int totalWeight = 0;

    public RandomBox(int totalWeight, List<RanOpt> optList) {
        this.totalWeight = totalWeight;
        this.optList = optList;
    }

    List<RanOpt> optList = new ArrayList<>();

    public static <T> Builder<T> builder() {
        return new Builder<>();
    }

    public static class Builder<T> {
        int totalWeight = 0;

        public Builder<T> totalWeight(int totalWeight) {
            this.totalWeight = totalWeight;
            return this;
        }

        public Builder<T> optList(List<RanOpt> optList) {
            this.optList = optList;
            return this;
        }

        @Override
        public String toString() {
            return "RandomBox.Builder(totalWeight=" + this.totalWeight + ", optList=" + this.optList + ")";
        }

        List<RanOpt> optList = new ArrayList<>();

        public Builder add(T value, int weight) {
            RanOpt<T> ranOpt = new RanOpt<>(value, weight);
            this.totalWeight += weight;
            for (int i = 0; i < weight; i++) {
                this.optList.add(ranOpt);
            }
            return this;
        }

        public RandomBox<T> build() {
            return new RandomBox<>(this.totalWeight, this.optList);
        }
    }

    public RandomBox(String... values) {
        for (String value : values) {
            this.totalWeight++;
            this.optList.add(new RanOpt<>(value, 1));
        }
    }

    public RandomBox(RanOpt<T>... opts) {
        for (RanOpt<T> opt : opts) {
            this.totalWeight += opt.getWeight();
            for (int i = 0; i < opt.getWeight(); i++) {
                this.optList.add(opt);
            }
        }
    }

    public RandomBox(int trueWeight, int falseWeight) {
        this((RanOpt<T>[])new RanOpt[] { new RanOpt<>(Boolean.valueOf(true), trueWeight), new RanOpt<>(Boolean.valueOf(false), falseWeight) });
    }

    public RandomBox(String trueRate) {
        this(ParamUtil.checkRatioNum(trueRate).intValue(), 100 - ParamUtil.checkRatioNum(trueRate).intValue());
    }

    public T getValue() {
        if (this.totalWeight == 0) {
            return null;
        }
        int i = (new Random()).nextInt(this.totalWeight);
        return ((RanOpt<T>)this.optList.get(i)).getValue();
    }

    public RanOpt<T> getRandomOpt() {
        int i = (new Random()).nextInt(this.totalWeight);
        return this.optList.get(i);
    }

    public String getRandStringValue() {
        int i = (new Random()).nextInt(this.totalWeight);
        return ((RanOpt<String>)this.optList.get(i)).getValue();
    }

    public Integer getRandIntValue() {
        int i = (new Random()).nextInt(this.totalWeight);
        return ((RanOpt<Integer>)this.optList.get(i)).getValue();
    }

    public Boolean getRandBoolValue() {
        int i = (new Random()).nextInt(this.totalWeight);
        return ((RanOpt<Boolean>)this.optList.get(i)).getValue();
    }

    public static void main(String[] args) {
        RanOpt[] opts = { new RanOpt<>("zhang3", 20), new RanOpt<>("li4", 30), new RanOpt<>("wang5", 50) };
        RandomBox randomBox = new RandomBox((RanOpt<?>[])opts);
        for (int i = 0; i < 10; i++) {
            System.out.println(randomBox.getRandomOpt().getValue());
        }
    }
}

